package bll

import (
	"encoding/hex"
	"fmt"
	"signal/lib/trace_log"

	"gitlab.local/backend/proto/dto"
	log "signal/collector/logger"
	"signal/event"
	"signal/model"
	"signal/utils"
)

var Report = &report{}

// 服务端处理设备上报数据
type report struct{}

func (r *report) init() func() {
	return func() {}
}

// Location 服务端获取设备GPS位置数据
func (r *report) Location(sn string, body []byte) error {
	var (
		err      error
		t        uint32
		lat      uint32
		lng      uint32
		gpsSpeed uint16
		bearing  uint16
		speed    uint8
		location *dto.Location
	)

	utils.Reverse(body)
	reader := utils.NewBitReader(body)

	if speed, err = reader.ReadBits8(8); err != nil {
		log.Errorf("parse time error: %s", err)
		return err
	}

	if bearing, err = reader.ReadBits16(16); err != nil {
		log.Errorf("parse Lat error: %s", err)
		return err
	}

	if gpsSpeed, err = reader.ReadBits16(16); err != nil {
		log.Errorf("parse Lat error: %s", err)
		return err
	}

	if lng, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse time error: %s", err)
		return err
	}
	if lat, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse time error: %s", err)
		return err
	}

	if t, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse time error: %s", err)
		return err
	}

	location = &dto.Location{
		Sn:       sn,
		Time:     int32(t),
		Speed:    int32(speed),
		Lat:      int32(lat),
		Lng:      int32(lng),
		GpsSpeed: int32(gpsSpeed),
		Bearing:  int32(bearing),
	}
	log.Infof("got report location: %v", *location)

	event.E.PublishAsync(event.DeviceLocationReport, location)
	return err
}

// Alarm 服务端获取设备告警数据
func (r *report) Alarm(sn string, data []byte) error {
	var (
		err error
		rd  = &model.ReportData{}
	)

	utils.Reverse(data)
	reader := utils.NewBitReader(data)

	// 0x76
	// read alarm info
	// skip remaining bit
	if err = reader.SkipBits(1); err != nil {
		log.Errorf("parse data error: %s", err)
	}

	if rd.NoGps, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.BatteryDisconnected, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.LowPower, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.Dump, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.Pressure, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.Rotation, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	if rd.Shock, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return err
	}

	// 上报震动
	r.reportAlarm(sn, rd)
	return nil
}

// OTAUpgrade 服务端处理设备OTA升级请求
func (r *report) OTAUpgrade(sn string, data []byte) error {
	defer utils.ExceptionCatch()
	var (
		otaUpgrade = &dto.OTAUpgradeNtf{Sn: sn}
	)

	trace_log.DebugLogger(sn, "OTAUpgrade", "ota upgrade data: ", hex.EncodeToString(data))
	utils.Reverse(data)
	rd := utils.NewBitReader(data)
	if result, err := rd.ReadBits8(8); err != nil {
		trace_log.DebugLogger(sn, "OTAUpgrade", "parse result error: ", err)
		return err
	} else {
		otaUpgrade.Result = int32(result)
	}

	event.E.PublishAsync(event.DeviceOTA, otaUpgrade)
	return nil
}

// OTAUpgradeBSC22 服务端处理设备OTA升级请求
func (r *report) OTAUpgradeBSC22(sn string, data *PacketBSC22) error {
	defer utils.ExceptionCatch()
	var (
		otaUpgrade = &dto.UpgradeBSC22Data{
			UpgradeCmd:  dto.BSC22UpgradeCmdType(data.Cmd),
			Id:          data.ID,
			DeviceType:  int32(data.DeviceType),
			Sn:          sn,
			BindLength:  data.BindLength,
			BindAddress: data.BindAddress,
			Body:        data.Body,
			Crc32:       data.Crc32,
		}
	)

	trace_log.DebugLogger(sn, "OTAUpgradeBSC22", "ota upgrade data: %s", hex.EncodeToString(data.ToHexBytes()))
	event.E.PublishAsync(event.DeviceOTA, otaUpgrade)
	return nil
}

// Fault 服务端处理设备故障上报
func (r *report) Fault(sn string, data []byte) error {
	var (
		err        error
		faultCheck = &dto.FaultCheck{Sn: sn}
	)

	utils.Reverse(data)
	rd := utils.NewBitReader(data)

	// byte 11 handle
	if data[0] != 0 {
		rd = utils.NewBitReader([]byte{data[0]})
		// skip 4 bits
		_ = rd.SkipBits(4)
		// 电池寿命终止故障EOL
		if eol, err := rd.ReadBits8(2); err == nil {
			if eol > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryEOFEOL
				fault.Level = dto.FaultLevel(eol)

				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 充电MOS故障
		if inMos, err := rd.ReadBits8(2); err == nil {
			if inMos > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultChargeMos
				fault.Level = dto.FaultLevel(inMos)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}

	// byte 10 handle
	if data[1] != 0 {
		rd = utils.NewBitReader([]byte{data[1]})
		// 放电MOS故障
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultDischargeMOS
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 预放电MOS故障
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultPreDischargeMOS
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池内部通讯异常
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryInternalCommunication
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池温度采集异常
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryTemperatureCollection
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}

	}

	// byte 9 handle
	if data[2] != 0 {
		rd = utils.NewBitReader([]byte{data[2]})
		// 单体电压采集异常(断线或短路)
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryDisconnectionShortCircuit
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		rd.SkipBits(2)
		// 电池短路
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryShortCircuit
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池绝缘过低
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultInsulationLow
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}

	}

	// byte 8 handle
	if data[3] != 0 {
		rd = utils.NewBitReader([]byte{data[3]})
		// 电池SOC过低
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultSOCLow
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池预放超时
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultPreDischargeTimeout
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池预放过流
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultPreDischargeOverCurrent
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池放电过流
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultDischargeOverCurrent
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}

	// byte 7 handle
	if data[4] != 0 {
		rd = utils.NewBitReader([]byte{data[4]})
		// 电池回馈过流
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultFeedbackOverCurrent
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池充电过流
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultChargingOverCurrent
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池预放电阻温度过高
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultResistorTemperatureHigh
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池MOS温度过高
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultMOSTemperatureHigh
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}

	// byte 6 handle
	if data[5] != 0 {
		rd = utils.NewBitReader([]byte{data[5]})
		// 电池均衡温度过高
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryEqualizationTemperatureHigh
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池温差过大
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryTemperatureDiffTooLarge
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池放电低温
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryDischargeLowTemperature
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池放电高温
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryDischargeHighTemperature
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}
	// byte 5 handle
	if data[6] != 0 {
		rd = utils.NewBitReader([]byte{data[6]})
		// 电池充电低温
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryChargingLowTemperature
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电池充电过温
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBatteryChargingOverheating
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 0V 禁用
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_Fault0VDisabled
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// skip 2 bits
		rd.SkipBits(2)
	}

	// byte 4 handle
	if data[7] != 0 {
		rd = utils.NewBitReader([]byte{data[7]})
		// 总压欠压
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultOverallUnderVoltage
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 总压过压
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultOverPressure
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 单体欠压
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultMonomerUnderVoltage
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 单体过压
		if d, err := rd.ReadBits8(2); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultMonomerOverpressure
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}

	// byte 3 handle
	// 预留
	if data[8] != 0 {

	}
	// skip byte 3
	rd.SkipBits(8)

	// byte 2 handle
	if data[9] != 0 {
		rd = utils.NewBitReader([]byte{data[9]})
		rd.SkipBits(3)
		// 刹车故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBrakeLever
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电机故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultEngine
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 转把故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultHandlebar
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 控制器故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultController
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 低压报警
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultLowVoltageAlarm
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}
	// byte 1 handle
	if data[10] != 0 {
		fault := &dto.Fault{Sn: sn}
		rd = utils.NewBitReader([]byte{data[10]})
		fault.Type = dto.FaultType_FaultController
		fault.Level = dto.FaultLevel(1)
		faultCheck.FaultList = append(faultCheck.FaultList, fault)
		event.E.PublishAsync(event.DeviceFault, fault)
	}
	// byte 0 handle
	if data[11] != 0 {
		rd = utils.NewBitReader([]byte{data[11]})
		// 控制器保护
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultControllerProtection
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 欠压保护
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultUnderVoltage
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 飞车保护故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultOverSpeedProtection
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 堵转保护
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultStallProtection
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 转把故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultHandlebar
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 刹车故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultBrakeLever
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 霍尔故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultHall
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
		// 电机故障
		if d, err := rd.ReadBits8(1); err == nil {
			if d > 0 {
				fault := &dto.Fault{Sn: sn}
				fault.Type = dto.FaultType_FaultEngine
				fault.Level = dto.FaultLevel(d)
				faultCheck.FaultList = append(faultCheck.FaultList, fault)
				event.E.PublishAsync(event.DeviceFault, fault)
			}
		}
	}

	// 故障检查
	event.E.PublishAsync(event.DeviceFaultCheck, faultCheck)
	return err
}

// ReportEveryMinute 服务端处理设备定时的快捷数据上报
func (r *report) ReportEveryMinute(sn string, body []byte) error {
	var (
		err error
		rd  = &model.ReportData{}
	)

	trace_log.DebugLogger(sn, " [receive report data] [every minute] [hex data:", hex.EncodeToString(body), "]", "[sn: ", sn, " ]")
	// parse hex data to struct
	if rd, err = r.parseReportData(body); err != nil {
		log.Errorf("parse report data error: %s", err)
		trace_log.DebugLogger(sn, "ReportEveryMinute parse error")
		return err
	}

	if len(body) != 28 {
		trace_log.DebugLogger(sn, " [receive report data] [every minute] [report data:", utils.ToJsonString(rd), " len:", len(body), "]", "[sn: ", sn, " ]")
		trace_log.DebugLogger(sn, "ReportEveryMinute error body is illegal")
	}

	trace_log.DebugLogger(sn, "ReportEveryMinute data:", utils.ToJsonString(rd))

	if len(body) > 28 {
		// 1. report battery lock state
		r.reportBatteryLock(sn, rd)
	}

	// 3. report location
	r.reportLocation(sn, rd)

	// 5. report gps and 4g signal info
	r.reportSignal(sn, rd)

	// 6. report alarm
	r.reportAlarm(sn, rd)

	// 7. report device stop status
	r.reportDevicePowerStatus(sn, rd)

	// 8. report 上锁状态
	r.reportLock(sn, rd)

	return err
}

// FullReport 服务端处理设备全量数据上报
func (r *report) FullReport(sn string, body []byte) error {
	var (
		err error
		rd  = &model.ReportData{}
	)

	// parse hex data to struct
	if rd, err = r.parseReportData(body); err != nil {
		log.Errorf("parse report data error: %s", err)
		return err
	}

	trace_log.DebugLogger(sn, "FullReport data:", utils.ToJsonString(rd))

	if len(body) > 28 {
		trace_log.DebugLogger(sn, " [receive report data] [FullReport] [report data:", utils.ToJsonString(rd), " len:", len(body), "]", "[sn: ", sn, " ]")
		// 1. report battery lock state
		r.reportBatteryLock(sn, rd)
	}

	// 3. report location
	r.reportLocation(sn, rd)

	// 4. report battery info
	r.reportBattery(sn, rd)

	// 5. report gps and 4g signal info
	r.reportSignal(sn, rd)

	// 6. report alarm
	r.reportAlarm(sn, rd)

	// 7. report device stop status
	r.reportDevicePowerStatus(sn, rd)

	// 8. report 固件版本
	r.reportControl(sn, rd)

	// 9. report 上锁状态
	r.reportLock(sn, rd)
	return err
}

func (r *report) parseReportData(data []byte) (*model.ReportData, error) {
	var (
		err error
		rd  = &model.ReportData{}
	)

	utils.Reverse(data)
	reader := utils.NewBitReader(data)

	// if data > 24 then data is 0x8A else data is 0x82
	if len(data) > 28 {
		// 0x66
		if err = reader.SkipBits(48); err != nil {
			log.Errorf("parse data error: %s", err)
		}

		// 0x41
		if err = reader.SkipBits(16); err != nil {
			log.Errorf("parse data error: %s", err)
		}

		// 0x14
		var a, b, c, d uint8
		if a, err = reader.ReadBits8(8); err != nil {
			fmt.Sprintf("parse SignalGps error: %s", err)
			return rd, err
		}
		if b, err = reader.ReadBits8(8); err != nil {
			fmt.Sprintf("parse SignalGps error: %s", err)
			return rd, err
		}
		if c, err = reader.ReadBits8(8); err != nil {
			fmt.Sprintf("parse SignalGps error: %s", err)
			return rd, err
		}
		if d, err = reader.ReadBits8(8); err != nil {
			fmt.Sprintf("parse SignalGps error: %s", err)
			return rd, err
		}
		rd.FirmwareVersion = fmt.Sprintf("%d.%d.%d.%d", a, b, c, d)

		// 0x52
		if rd.RunMode, err = reader.ReadBits8(8); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		// 0x62
		// skip the switch is enabled data
		if err = reader.SkipBits(8); err != nil {
			log.Errorf("parse data error: %s", err)
		}

		// skip remaining two bits
		if err = reader.SkipBits(2); err != nil {
			log.Errorf("parse data error: %s", err)
		}

		if rd.HelmetLock, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		if rd.BatteryLock, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		if rd.Direction, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		if rd.Disarm, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		if rd.Switch, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}

		// read switch data
		if rd.Acc, err = reader.ReadBits8(1); err != nil {
			log.Errorf("parse SignalGps error: %s", err)
			return rd, err
		}
	}

	// 0x61
	// read power status
	if rd.LockStatus, err = reader.ReadBits8(4); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.PowerStatus, err = reader.ReadBits8(4); err != nil {
		log.Errorf("parse PowerStatus error: %s", err)
		return rd, err
	}

	// 0x76
	// read alarm info
	// skip remaining bit
	if err = reader.SkipBits(1); err != nil {
		log.Errorf("parse data error: %s", err)
	}

	if rd.NoGps, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.BatteryDisconnected, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.LowPower, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.Dump, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.Pressure, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.Rotation, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.Shock, err = reader.ReadBits8(1); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	// 0x74
	// read signal info
	if rd.SignalGps, err = reader.ReadBits8(8); err != nil {
		log.Errorf("parse SignalGps error: %s", err)
		return rd, err
	}

	if rd.Signal4G, err = reader.ReadBits8(8); err != nil {
		log.Errorf("parse Signal4G error: %s", err)
		return rd, err
	}

	// 0x73
	if rd.BatteryStatus, err = reader.ReadBits8(8); err != nil {
		log.Errorf("parse Mileage error: %s", err)
		return rd, err
	}

	if rd.Mileage, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse Mileage error: %s", err)
		return rd, err
	}

	if rd.Electricity, err = reader.ReadBits16(16); err != nil {
		log.Errorf("parse Mileage error: %s", err)
		return rd, err
	}

	// 0x72 data
	if rd.Speed, err = reader.ReadBits8(8); err != nil {
		log.Errorf("parse Speed error: %s", err)
		return rd, err
	}
	// 0x71
	// read location info

	if rd.Bearing, err = reader.ReadBits16(16); err != nil {
		log.Errorf("parse Bearing error: %s", err)
		return rd, err
	}

	if rd.GpsSpeed, err = reader.ReadBits16(16); err != nil {
		log.Errorf("parse GpsSpeed error: %s", err)
		return rd, err
	}

	if rd.Lng, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse Lng error: %s", err)
		return rd, err
	}
	if rd.Lat, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse Lat error: %s", err)
		return rd, err
	}

	// 0x51
	if rd.Time, err = reader.ReadBits32(32); err != nil {
		log.Errorf("parse time error: %s", err)
		return rd, err
	}
	return rd, err
}

func (r *report) reportLocation(sn string, rd *model.ReportData) {
	// emit event location
	location := &dto.Location{
		Sn:       sn,
		Time:     int32(rd.Time),
		Speed:    int32(rd.Speed),
		Lat:      int32(rd.Lat),
		Lng:      int32(rd.Lng),
		Mileage:  int32(rd.Mileage),
		Bearing:  int32(rd.Bearing),
		GpsSpeed: int32(rd.GpsSpeed),
	}
	event.E.PublishAsync(event.DeviceLocationReport, location)
}

func (r *report) reportAlarm(sn string, rd *model.ReportData) {
	alarm := &dto.Alarm{Sn: sn}

	if rd.Shock != 0 {
		shock := int32(rd.Shock)
		alarm.Shock = &shock
	}
	if rd.Rotation != 0 {
		rotation := int32(rd.Rotation)
		alarm.Rotation = &rotation
	}
	if rd.Pressure != 0 {
		pressure := int32(rd.Pressure)
		alarm.Pressure = &pressure
	}
	if rd.Dump != 0 {
		dump := int32(rd.Dump)
		alarm.Dump = &dump
	}
	if rd.LowPower != 0 {
		lowPower := int32(rd.LowPower)
		alarm.LowPower = &lowPower
	}
	if rd.BatteryDisconnected != 0 {
		batteryDisconnected := int32(rd.BatteryDisconnected)
		alarm.BatteryDisconnected = &batteryDisconnected
	}
	if rd.NoGps != 0 {
		noGps := int32(rd.NoGps)
		alarm.NoGps = &noGps
	}

	event.E.PublishAsync(event.DeviceAlarm, alarm)
}

func (r *report) reportBatteryLock(sn string, rd *model.ReportData) {
	ed := &dto.DeviceStatus{
		Sn:    sn,
		Event: dto.EventType_BatteryLock,
	}
	event.E.PublishAsync(event.DeviceStatusChange, ed)
}

func (r *report) reportBattery(sn string, rd *model.ReportData) {
	var isQuantity = rd.IsQuantity == 1

	ed := &dto.BatteryInfo{
		Sn:       sn,
		Status:   model.IntToDtoBatteryStatus(rd.BatteryStatus),
		Quantity: isQuantity,
		Val:      int32(rd.Electricity),
		Mileage:  int32(rd.Mileage),
	}
	trace_log.DebugLogger(sn, "reportBattery,data:", utils.ToJsonString(ed))

	event.E.PublishAsync(event.DeviceBatteryReport, ed)
}

func (r *report) reportSignal(sn string, rd *model.ReportData) {
	ed := &dto.Signal{
		Sn:        sn,
		SignalGps: int32(rd.SignalGps),
		Signal_4G: int32(rd.Signal4G),
	}

	event.E.PublishAsync(event.DeviceSignalReport, ed)
}

func (r *report) reportControl(sn string, rd *model.ReportData) {
	ed := &dto.Controller{
		Sn:              sn,
		FirmwareVersion: rd.FirmwareVersion,
	}

	event.E.PublishAsync(event.DeviceControlReport, ed)
}

func (r *report) reportLock(sn string, rd *model.ReportData) {
	eData := &dto.DeviceStatus{
		Sn: sn,
	}

	switch rd.LockStatus {
	case model.DeviceLock:
		eData.Event = dto.EventType_Lock
	case model.DeviceUnlock:
		eData.Event = dto.EventType_Unlock
	}
	event.E.PublishAsync(event.DeviceStatusChange, eData)
}

func (r *report) reportDevicePowerStatus(sn string, rd *model.ReportData) {
	var e dto.EventType

	switch rd.PowerStatus {
	case 0:
		e = dto.EventType_PowerOff
	default:
		//case 1:
		e = dto.EventType_PowerOn
	}

	trace_log.DebugLogger(sn, "--------- 车辆启动 value:", e.String(), " ---------")

	ed := &dto.DeviceStatus{
		Sn:    sn,
		Event: e,
	}
	event.E.PublishAsync(event.DeviceStatusChange, ed)
}
